//
//  AdjacencyList.swift
//  Chapter3LinkedList
//
//  Created by TRS-Mobile on 2021/9/3.
//

import Foundation

/// 邻接表
class AdjacencyList<T>: Graph {
    
    typealias E = T
    
    var adjacencies: [Vertex<T>: [Edge<T>]] = [:]
    var vertices: [Vertex<T>] {
        return Array(adjacencies.keys)
    }
    
    init() {}
    
    @discardableResult
    func createVertex(data: T) -> Vertex<T> {
        let vertex = Vertex(index: adjacencies.count, data: data)
        adjacencies[vertex] = []
        return vertex
    }
    
    func addDirectedEdge(frome source: Vertex<T>, to destination: Vertex<T>, weight: Double?) {
        let edge = Edge(source: source, destination: destination, weight: weight)
        adjacencies[source]?.append(edge)
    }
    
    func edges(from source: Vertex<T>) -> [Edge<T>] {
        return adjacencies[source] ?? []
    }
    
    func weight(from source: Vertex<T>, to destination: Vertex<T>) -> Double? {
        return edges(from: source)
            .first { $0.destination == destination }?
            .weight
    }
}

extension AdjacencyList: CustomStringConvertible {
    var description: String {
        var result = ""
        for (vertex, edges) in adjacencies {
            var edgString = ""
            for (idx, edge) in edges.enumerated() {
                if idx != edges.count - 1 {
                    edgString.append("\(edge.destination),")
                }else {
                    edgString.append("\(edge.destination)")
                }
            }
            result.append("\(vertex) ---> [\(edgString)]\n" )
        }
        return result
    }
}
